package com.vrp3d.common.utils;

import org.springframework.stereotype.Component;

import java.util.Random;
import java.util.UUID;

/**
 * 随机数工具类
 *
 * @author vrp3d
 */
@Component
public class RandomUtil {

    private static final String ALL_CHAR = "-@#%*_abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String LETTER_CHAR = "0123456789abcdefghijkllmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public static final String NUMBERCHAR = "0123456789";

    /**
     * 返回一个定长的带因子的固定的随机字符串(只包含大小写字母、数字)
     *
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String generateStringByKey(int length, int channel) {
        StringBuilder sb = new StringBuilder();
        Random random = new Random(channel);
        for (int i = 0; i < length; i++) {
            sb.append(ALL_CHAR.charAt(random.nextInt(ALL_CHAR.length())));
        }
        return sb.toString();
    }

    /**
     * 返回一个定长的随机字符串(只包含大小写字母、数字)
     *
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String generateString(int length) {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(LETTER_CHAR.charAt(random.nextInt(LETTER_CHAR.length())));
        }
        return sb.toString();
    }

    /**
     * 返回一个定长的随机纯字母字符串(只包含大小写字母)
     *
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String generateMixString(int length) {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(LETTER_CHAR.charAt(random.nextInt(LETTER_CHAR.length())));
        }
        return sb.toString();
    }

    /**
     * 返回一个定长的随机纯小写字母字符串
     *
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String generateLowerString(int length) {
        return generateMixString(length).toLowerCase();
    }

    /**
     * 返回一个定长的随机纯da写字母字符串
     *
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String generateUpperString(int length) {
        return generateMixString(length).toUpperCase();
    }

    /**
     * 生成一个定长的纯0字符串
     *
     * @param length 字符串长度
     * @return 纯0字符串
     */
    public static String generateZeroString(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append('0');
        }
        return sb.toString();
    }

    /**
     * 根据数字生成一个定长的字符串，长度不够前面补0
     *
     * @param num       数字
     * @param fixdLenth 字符串长度
     * @return 定长的字符串
     */
    public static String toFixdLengthString(long num, int fixdLenth) {
        StringBuilder sb = new StringBuilder();
        String strNum = String.valueOf(num);
        if (fixdLenth - strNum.length() >= 0) {
            sb.append(generateZeroString(fixdLenth - strNum.length()));
        } else {
            throw new RuntimeException("将数字" + num + "转化为长度为" + fixdLenth + "的字符串发生异常！");
        }
        sb.append(strNum);
        return sb.toString();
    }

    /**
     * 每次生成的len位数都不相同
     *
     * @param param
     * @return 定长的数字
     */
    public static int getNotSimple(int[] param, int len) {
        Random rand = new Random();
        for (int i = param.length; i > 1; i--) {
            int index = rand.nextInt(i);
            int tmp = param[index];
            param[index] = param[i - 1];
            param[i - 1] = tmp;
        }
        int result = 0;
        for (int i = 0; i < len; i++) {
            result = result * 10 + param[i];
        }
        return result;
    }

    /**
     * 生成指定位数的随机数,int类型
     *
     * @param numberOfDigits
     * @return
     */
    public static int generateNumberInt(int numberOfDigits) {
        int temp = (int) Math.pow(10, numberOfDigits - 1);
        return (int) (((Math.random() * 9) + 1) * temp);
    }

    /**
     * 生成指定位数的整数随机数返回String类型
     *
     * @param numberOfDigits
     * @return
     */
    public static String generateNumberString(int numberOfDigits) {
        Random random = new Random();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < numberOfDigits; i++) {
            stringBuilder.append(random.nextInt(9));
        }
        return stringBuilder.toString();
    }

    /**
     * UUID
     *
     * @return
     */
    public static String getUuid() {
        return UUID.randomUUID().toString();
    }

    /**
     * UUID没有横线-
     *
     * @return
     */
    public static String getUuidWithOutHorizontalLine() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 生成一个从1到max的n个不重复的随机数,并且按照大小排序
     *
     * @param max 最大值
     * @param n   个数
     * @return 随机数数组
     */
    public static Integer[] randomNumberFromOne(int max, int n) {
        return randomNumber(1, max, n);
    }

    /**
     * 产生min-max中的n个不重复的随机数
     *
     * @param min :产生随机数的其实位置
     * @param max :产生随机数的最大位置
     * @param n   :所要产生多少个随机数
     * @return
     */
    public static Integer[] randomNumber(int min, int max, int n) {
        int len = max - min + 1;

        if (max < min || n > len) {
            return null;
        }

        // 初始化给定范围的待选数组
        Integer[] source = new Integer[len];
        for (int i = min; i < min + len; i++) {
            source[i - min] = i;
        }

        Integer[] result = new Integer[n];
        Random rd = new Random();
        int index;
        for (int i = 0; i < result.length; i++) {
            // 待选数组0到(len-2)随机一个下标
            index = Math.abs(rd.nextInt() % len--);
            // 将随机到的数放入结果集
            result[i] = source[index];
            // 将待选数组中被随机到的数，用待选数组(len-1)下标对应的数替换
            source[index] = source[len];
        }
        return result;
    }
}
